using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using FE;
namespace WinXnaFE
{
    public class SelectCursor
    {
        public Vector2 position = new Vector2();

        public Texture2D texture;
        public Map map;
        public SelectCursor(Texture2D texture, Map map)
        {
            this.texture = texture;
            this.map = map;
            int repeatDelay = 500, repeatSustain = 120;
            right = new InputBuffer<bool>(false, repeatDelay, repeatSustain);
            left = new InputBuffer<bool>(false, repeatDelay, repeatSustain);
            up = new InputBuffer<bool>(false, repeatDelay, repeatSustain);
            down = new InputBuffer<bool>(false, repeatDelay, repeatSustain);
        }
        InputBuffer<bool> right, left, up, down;
        public void Input(GamePadState gamePadState, double elapsedTime)
        {
            right.Set(gamePadState.DPad.Right == ButtonState.Pressed, elapsedTime);
            left.Set(gamePadState.DPad.Left == ButtonState.Pressed, elapsedTime);
            up.Set(gamePadState.DPad.Up == ButtonState.Pressed, elapsedTime);
            down.Set(gamePadState.DPad.Down == ButtonState.Pressed, elapsedTime);

            if (right.HasNewEvent && right.NewEvent)
            {
                position.X += 1;
                if (position.X >= map.Width) position.X = map.Width - 1;
            }
            if (left.HasNewEvent && left.NewEvent)
            {
                position.X -= 1;
                if (position.X < 0) position.X = 0;
            }
            if (up.HasNewEvent && up.NewEvent)
            {
                position.Y -= 1;
                if (position.Y < 0) position.Y = 0;
            }
            if (down.HasNewEvent && down.NewEvent)
            {
                position.Y += 1;
                if (position.Y >= map.Height) position.Y = map.Height - 1;
            }
        }
        public void Draw(SpriteBatch batch, double elapsedTime)
        {
            Vector2 drawPos = new Vector2(position.X, position.Y);
            drawPos.X *= 100;
            drawPos.Y *= 85;
            drawPos.Y -= 40;
            batch.Draw(texture, drawPos, Color.White);
        }
    }

    public class InputBuffer <T>
    {
        T lastValue;
        T currentValue;

        T newValue;

        bool hasNewEvent = false;
        bool repeating = false;
        double repeatDelay;
        double repeatSustain;

        T restingState;

        double currentDelay = 0; 

        public InputBuffer(T restingState, double repeatDelay, double repeatSustain)
        {
            this.restingState = restingState;
            this.repeatDelay = repeatDelay;
            this.repeatSustain = repeatSustain;
        }

        public void Set(T value, double elapsedTime)
        {
            lastValue = currentValue;
            currentValue = value;

            if (!lastValue.Equals(currentValue))
            {
                hasNewEvent = true;
                newValue = currentValue;
                currentDelay = 0;
                repeating = false;
            }
            else
            {
                if (!currentValue.Equals(restingState))
                {
                    currentDelay += elapsedTime;
                    if (currentDelay >= repeatDelay)
                    {
                        repeating = true;
                        currentDelay = 0;
                        hasNewEvent = true;
                        newValue = currentValue;
                    }
                    if (repeating)
                    {
                        if (currentDelay >= repeatSustain)
                        {
                            currentDelay = 0;
                            hasNewEvent = true;
                            newValue = currentValue;
                        }
                    }
                }
            }
        }
        public bool HasNewEvent
        {
            get { return hasNewEvent; }
        }
        public T NewEvent
        {
            get {
                hasNewEvent = false;
                return newValue; 
            }
        }
    }
}
